require "LevelHelper.Helpers.LHHelpers"


--notifications
LHPathMovementHasEndedGlobalNotification = "LHPathMovementHasEndedGlobalNotification"
LHPathMovementHasEndedPerSpriteNotification = "LHPathMovementHasEndedPerSpriteNotification"

LHPathMovementHasChangedPointGlobalNotification ="LHPathMovementHasChangedPointGlobalNotification"
LHPathMovementHasChangedPointPerSpriteNotification ="LHPathMovementHasChangedPointPerSpriteNotification"

LHPathNode = Core.class(Sprite)
function LHPathNode:initWithPoints(points, spriteObj)

    if (nil == points) then
        print("Invalid LHPathNode initialization!")
    end
        
    self.giderosSprite = spriteObj
    self.speed = 0.2
    self.interval = 0.01
    self.paused = false
    self.startAtEndPoint = false
    self.isCyclic = false
    self.restartOtherEnd = false
    self.axisOrientation = 0 -- 1 is x 2 is y
    self.flipX = false
    self.flipY = false
    self.pathPoints = lh_deepcopy(points)
    self.currentPoint = 1
    self.elapsed = 0.0
    self.isLine = true
    self.initialAngle = spriteObj:get("rotation")
    self.prevPathPosition = {x = 0, y = 0}
    self.time = os.clock()
    self.moveWithDelta = false
    self.firstTime = true
    
    if(#self.pathPoints > 0)then
        self.prevPathPosition =  self.pathPoints[1];
    end
    
    --Runtime:addEventListener( "enterFrame", object )

    self:addEventListener(Event.ENTER_FRAME, self.enterFrame, self)
    
    
    return object
end
--------------------------------------------------------------------------------
function LHPathNode:removeSelf()

    --print("path node remove self");

    self:removeEventListener(Event.ENTER_FRAME, self.enterFrame, self);
    self.giderosSprite = nil;    
    self.pathPoints = nil    
    self.speed = nil
    self.interval = nil
    self.startAtEndPoint = nil
    self.isCyclic = nil
    self.restartOtherEnd = nil
    self.axisOrientation = nil
    self.currentPoint = nil
    self.elapsed = nil
    self.initialAngle = nil
    self.time = nil
    self.isLine = nil
    self.paused = nil
    self.pathNotifierId = nil
    self.pathNotifierSel= nil
    self.firstTime = nil
    
    self = nil;
end
--------------------------------------------------------------------------------
function LHPathNode:restart()
    self.currentPoint = 1
    self.elapsed = 0.0
end
--------------------------------------------------------------------------------
function LHPathNode:setSpeed(val)
    self.speed = val;
    self.interval = self.speed/(#self.pathPoints-1);    
end
--------------------------------------------------------------------------------
function LHPathNode:setStartAtEndPoint(val)
    
    if(self.startAtEndPoint == val)then
        --we do this so that we dont reverse point over and over if 1 is given multiple times
        return
    end
    
    self.startAtEndPoint = val;
    
    if(self.startAtEndPoint == 1)then
        self.pathPoints = self:inversePoints(self.pathPoints)
    end
end
--------------------------------------------------------------------------------
function LHPathNode:setMoveUsingDelta(moveWithDelta)
    self.moveWithDelta = moveWithDelta
    if(false == moveWithDelta)then
        self.moveWithDelta = moveWithDelta
        local startPosition = self.pathPoints[1];
        self.giderosSprite:setPosition(startPosition.x, startPosition.y);
    end
end

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
--PRIVATE METHODS
--------------------------------------------------------------------------------
function LHPathNode:inversePoints(points)

    local invertedPoints = {}
    for i = #points,1,-1 do
        invertedPoints[#invertedPoints+1] = points[i]
    end
    
    points = nil;
    return invertedPoints
end
--------------------------------------------------------------------------------
function LHPathNode:rotationDegreeFromPoint ( srcObj, dstObj )
 
    local xDist = dstObj.x-srcObj.x
       local yDist = dstObj.y-srcObj.y
    local angleBetween = math.deg( math.atan( yDist/xDist ) )
        
    if ( srcObj.x < dstObj.x ) then 
        angleBetween = angleBetween+90
    else 
        angleBetween = angleBetween-90 
    end
        
    return angleBetween
end
--------------------------------------------------------------------------------
function LHPathNode:MIN(A, B)

    if(A < B)then
        return A;
    else
        return B;
    end
    
    return A;
end
--------------------------------------------------------------------------------
function LHPathNode:enterFrame( event )
        
      
    if(self == nil)then
        return;
    end
    
    local callPathNotification = false;
    
    if(self.firstTime)then
        self.time = event.time
        self.firstTime = false
    end

    if(nil == self.giderosSprite)then
        return;
    end
    
    if(self.paused)then 
        self.time       = event.time
        return;
    end
    
    if(nil == self.pathPoints)then
        return;
    end
    
    local startPosition = self.pathPoints[self.currentPoint];
    local previousPoint = self.currentPoint -1;
    if(previousPoint < 1)then
        previousPoint = 1;
    end
    
    local prevPosition = self.pathPoints[previousPoint];
    local endPosition = startPosition;
        
    local startAngle = self:rotationDegreeFromPoint(startPosition,prevPosition)
    if(self.currentPoint == 1)then
        startAngle = self.initialAngle-90;
    end
    
    local endAngle = startAngle;
    
    if( (self.currentPoint + 1) <= #self.pathPoints)then
        endPosition = self.pathPoints[self.currentPoint+1]
        endAngle = self:rotationDegreeFromPoint(endPosition,startPosition);        
    else 
        if(self.isCyclic)then
    
            if(false == self.restartOtherEnd)then
                self.pathPoints = self:inversePoints(self.pathPoints)
            end
            
            if(self.flipX)then
                self.giderosSprite:setScaleX(-1*self.giderosSprite:getScaleX());
            end
            
            if(self.flipY)then
                self.giderosSprite:setScaleY(-1*self.giderosSprite:getScaleY());
            end
            
            self.currentPoint = 0;
        end
        
        callPathNotification = true;
    end
    
    if(self.axisOrientation == 1)then
        startAngle =startAngle+ 90.0;
    end
    if(self.axisOrientation == 1)then
        endAngle = endAngle + 90.0;
    end
    
    if(startAngle > 360)then
        startAngle = startAngle - 360;
    end
    if(endAngle > 360)then
        endAngle = endAngle - 360;
    end
        
    --print("elapsed/interval " .. (self.elapsed) .. " " .. (self.interval) .. " = " .. (self.elapsed/self.interval))
    local t = self:MIN(1.0, self.elapsed/self.interval);
    
    local deltaP = lh_Sub( endPosition, startPosition );
    
    local newPos = {x = startPosition.x + deltaP.x * t, 
                    y = startPosition.y + deltaP.y * t};
            
    if(startAngle > 270 and startAngle < 360 and
       endAngle > 0 and endAngle < 90)then
        startAngle = startAngle - 360;
    end
    
    
    if(startAngle > 0 and startAngle < 90 and
       endAngle < 360 and endAngle > 270)then
        startAngle = startAngle + 360;
    end
    
    local deltaA = endAngle - startAngle;
    local newAngle = startAngle + deltaA*t;

    if(newAngle > 360)then
        newAngle = newAngle - 360;
    end
    
    if(nil ~= self.giderosSprite)then
    
        local gx,gy = self.giderosSprite:getPosition();
    
        local sprPos = {     x = gx, y = gy};
        local sprDelta={     x = newPos.x - self.prevPathPosition.x, 
                            y = newPos.y - self.prevPathPosition.y};
        
        self.giderosSprite:transformPosition(sprPos.x + sprDelta.x, sprPos.y + sprDelta.y)
        
        if(self.moveWithDelta == false)then
            self.giderosSprite:transformPosition(newPos.x, newPos.y);
        end
        
        --print("NEW POS " .. (newPos.x) .. " " .. (newPos.y));
        --print("PRE POS " .. (self.prevPathPosition.x) .. " " .. (self.prevPathPosition.y));
        --print("DELTA " .. (sprDelta.x) .. " " .. (sprDelta.y));
        
        --print("path enterFrame " .. " " .. (t) .. " X : " .. (self.giderosSprite:getX()) .. " Y " .. (self.giderosSprite:getY()));
        
        self.prevPathPosition = newPos;        
    end


    if(self.axisOrientation ~= 0)then
        self.giderosSprite:transformRotation(newAngle);
    end
    
    if(self.isLine)then
        if(self.axisOrientation ~= 0)then
            self.giderosSprite:transformRotation(endAngle);
        end
    end
    
    local dist = lh_Distance(self.prevPathPosition, endPosition);
        
    if(0.001 > dist)then
        if(self.currentPoint + 1 <= #self.pathPoints)then
            self.elapsed = 0;
            self.currentPoint =self.currentPoint+ 1;     
            
            local changedEvent = { name=LHPathMovementHasChangedPointGlobalNotification, 
                                  object = self.giderosSprite } 
            --self:dispatchEvent(changedEvent);
            
            local changedEvent = { name=LHPathMovementHasChangedPointPerSpriteNotification, 
                                  object = self.giderosSprite } 
            --self.giderosSprite:dispatchEvent(changedEvent);

        end
    end
    
    self.elapsed  = self.elapsed + (event.time- self.time)
    self.time       = event.time 

    if(callPathNotification)then
    
            local endedEvent = { name=LHPathMovementHasEndedGlobalNotification, 
                                 object = self.giderosSprite } 
            --self:dispatchEvent(endedEvent);

            local endedEvent = { name=LHPathMovementHasEndedPerSpriteNotification, 
                                 object = self.giderosSprite } 
            --self.giderosSprite:dispatchEvent(endedEvent);

        if(false == self.isCyclic)then
            self.paused = true;
        end
    end
end
--------------------------------------------------------------------------------